import os
import sys
from typing import List, Dict, Optional

from game.game_manager import GameManager


class GameUI:
    def __init__(self):
        self._game_manager = GameManager()
        self._current_team1 = []
        self._current_team2 = []
        self._battle_active = False
    
    def start_game(self, game_manager: GameManager):
        self._game_manager = game_manager
        self._show_welcome()
        
        while True:
            try:
                self._show_main_menu()
                choice = input("\\n Please select the operation (1-6): ").strip()
                
                if choice == "1":
                    self._champion_selection()
                elif choice == "2":
                    self._item_management()
                elif choice == "3":
                    self._start_battle()
                elif choice == "4":
                    self._save_game()
                elif choice == "5":
                    self._load_game()
                elif choice == "6":
                    self._show_game_info()
                elif choice == "0":
                    print("\\n Thank you for playing League of Chang'An!Bye!")
                    break
                else:
                    print("\\n Invalid seletion,please re-enter.")
                    
            except KeyboardInterrupt:
                print("\\n\\n The game was interrupted by the user,goodbye!")
                break
            except Exception as e:
                print(f"\\n error occurred: {e}")
                input("Press enter to continue.")
    
    def _show_welcome(self):
        print("=" * 60)
        print("Welcome to League of Chang'An!")
        print("=" * 60)
        print("In this mysterious Chang'an City, powerful heroes will engage in epic battles.")
        print("Choose your hero, equip powerful items, and battle in the ancient arena.")
        print("=" * 60)
    
    def _show_main_menu(self):
        print("\\n" + "=" * 40)
        print("main menu")
        print("=" * 40)
        print("1. choose champion")
        print("2. item management")
        print("3. start battle")
        print("4. save game")
        print("5. load game")
        print("6. game information")
        print("0. quit game")
        
        if self._current_team1:
            print(f"\\n present team 1: {', '.join([c.name for c in self._current_team1])}")
        if self._current_team2:
            print(f"present team 2: {', '.join([c.name for c in self._current_team2])}")
    
    def _champion_selection(self):
        print("\\n" + "=" * 40)
        print("choose champion")
        print("=" * 40)
        
        while True:
            print("\\n choose champion:")
            print("1. team 1")
            print("2. team 2")
            print("0. return to main menu")
            
            team_choice = input("choose team (1/2/0): ").strip()
            
            if team_choice == "0":
                break
            elif team_choice in ["1", "2"]:
                self._select_champions_for_team(int(team_choice))
            else:
                print("invalid choice!")
    
    def _select_champions_for_team(self, team_num: int):
        available_champions = self._game_manager.get_available_champions()
        
        print(f"\\n team{team_num} choose champion")
        print("available champion:")
        
        for i, champion_name in enumerate(available_champions, 1):
            champion_info = self._game_manager.get_champion_info(champion_name)
            print(f"{i}. {champion_name} ({champion_info.get('type', 'Unknown')})")
            print(f"health: {champion_info.get('health', 0)}, attack: {champion_info.get('attack', 0)},defense: {champion_info.get('defense', 0)}")
        
        print("\\n select operation:")
        print("1. add champion")
        print("2. delete champion")
        print("3. view hero details")
        print("0. return")
        
        choice = input("selece operation: ").strip()
        
        if choice == "1":
            self._add_champion_to_team(team_num, available_champions)
        elif choice == "2":
            self._remove_champion_from_team(team_num)
        elif choice == "3":
            self._show_champion_details(available_champions)
        elif choice == "0":
            return
        else:
            print("invaild choice!")
    
    def _add_champion_to_team(self, team_num: int, available_champions: List[str]):
        try:
            champion_index = int(input(f"choose champion number (1-{len(available_champions)}): ")) - 1
            
            if 0 <= champion_index < len(available_champions):
                champion_name = available_champions[champion_index]
                champion = self._game_manager.create_champion(champion_name)
                
                if champion:
                    if team_num == 1:
                        if len(self._current_team1) < 5:  
                            self._current_team1.append(champion)
                            print(f"add {champion.name} to team 1")
                        else:
                            print("Team 1 is full(maximum of 5 heroes)")
                    else:
                        if len(self._current_team2) < 5:
                            self._current_team2.append(champion)
                            print(f"add {champion.name} to team 2")
                        else:
                            print("Team 2 is full(maximum of 5 heroes)")
                else:
                    print("Failed to create champion!")
            else:
                print("invalid champion number!")
        except ValueError:
            print("Please enter a valid number!")
    
    def _remove_champion_from_team(self, team_num: int):
        team = self._current_team1 if team_num == 1 else self._current_team2
        
        if not team:
            print(f"team {team_num} is empty!")
            return
        
        print(f"\\n team {team_num} present champion:")
        for i, champion in enumerate(team, 1):
            print(f"{i}. {champion.name} (grade {champion.level})")
        
        try:
            champion_index = int(input("Select the number of the hero to be removed: ")) - 1
            
            if 0 <= champion_index < len(team):
                removed_champion = team.pop(champion_index)
                print(f"remove {removed_champion.name}")
            else:
                print("invalid champion number!")
        except ValueError:
            print("Please enter a valid number!")
    
    def _show_champion_details(self, available_champions: List[str]):
        try:
            champion_index = int(input(f"choose champion number (1-{len(available_champions)}): ")) - 1
            
            if 0 <= champion_index < len(available_champions):
                champion_name = available_champions[champion_index]
                champion_info = self._game_manager.get_champion_info(champion_name)
                
                print(f"\\n {champion_name} detailed information")
                print(f"type: {champion_info.get('type', 'Unknown')}")
                print(f"health: {champion_info.get('health', 0)}")
                print(f"attack: {champion_info.get('attack', 0)}")
                print(f"defense: {champion_info.get('defense', 0)}")
                print(f"speed: {champion_info.get('speed', 0)}")
                print(f"mana: {champion_info.get('mana', 0)}")
                print("\\nability:")
                for ability in champion_info.get('abilities', []):
                    print(f"  - {ability}")
            else:
                print("invalid champion number!")
        except ValueError:
            print("Please enter a valid number!")
    
    def _item_management(self):
        print("\\n" + "=" * 40)
        print("Item Management")
        print("=" * 40)
        print("Developing the item management function")
        input("Press Enter to return to the main menu")
    
    def _start_battle(self):
        if not self._current_team1 or not self._current_team2:
            print("\\n Please select heroes for both teams first.!")
            input("press enter to return to main menu")
            return
        
        print("\\n" + "=" * 40)
        print("start battle!")
        print("=" * 40)
        
        result = self._game_manager.start_battle(self._current_team1, self._current_team2)
        
        if result["success"]:
            self._battle_active = True
            print(f"start battle! {result['message']}")
            self._battle_loop()
        else:
            print(f"fail to start battle: {result['message']}")
            input("press enter to return to main menu")
    
    def _battle_loop(self):
        while self._battle_active and self._game_manager.is_battle_active():
            print("\\n" + "-" * 40)
            print("battle continue")
            
            result = self._game_manager.execute_battle_turn(self._current_team1, self._current_team2)
            
            if result.get("battle_ended"):
                self._battle_active = False
                print(f"\\n game over! winner: {result['winner']}")
                if result.get("survivors"):
                    print(f"survivor: {', '.join(result['survivors'])}")
                print(f"total turns: {result['total_turns']}")
                break
            
            self._show_battle_status()
            
            input("\\n Press Enter to continue to the next round")
        
        input("\\n press enter to return to main menu")
    
    def _show_battle_status(self):
        print("\\n combat state")
        
        print("\\n team 1:")
        for champion in self._current_team1:
            status = "survive" if champion.is_alive else "die"
            print(f"  {champion.name}: {champion.health}/{champion.max_health} HP, {champion.mana}/{champion.max_mana} MP ({status})")
        
        print("\\n team 2:")
        for champion in self._current_team2:
            status = "survive" if champion.is_alive else "die"
            print(f"  {champion.name}: {champion.health}/{champion.max_health} HP, {champion.mana}/{champion.max_mana} MP ({status})")
    
    def _save_game(self):
        if not self._current_team1 and not self._current_team2:
            print("\\n No game state to save")
            input(" press enter to return to main menu")
            return
        
        save_name = input("\\n Enter the file name to save: ").strip()
        if not save_name:
            print("File name cannot be empty!")
            return
        
        if self._game_manager.save_game(self._current_team1, self._current_team2, save_name):
            print(f"save game: {save_name}")
        else:
            print("fail to save!")
        
        input("press enter to return to main menu")
    
    def _load_game(self):
        save_files = self._game_manager.get_save_files()
        
        if not save_files:
            print("\\n no saved game found!")
            input("press enter to return to main menu")
            return
        
        print("\\n Available for saving files:")
        for i, save_file in enumerate(save_files, 1):
            print(f"{i}. {save_file}")
        
        try:
            choice = int(input("Select the file number to save: ")) - 1
            if 0 <= choice < len(save_files):
                save_name = save_files[choice]
                game_data = self._game_manager.load_game(save_name)
                
                if game_data:
                    self._current_team1 = game_data["team1"]
                    self._current_team2 = game_data["team2"]
                    print(f"game load: {save_name}")
                else:
                    print("fail to load game!")
            else:
                print("invalid choice!")
        except ValueError:
            print("please enter valid number!")
        
        input("press enter to return to main menu")
    
    def _show_game_info(self):
        print("\\n" + "=" * 50)
        print("League of Chang'An game information")
        print("=" * 50)
        print("This is a turn-based combat game based on object-oriented programming.")
        print("\\n Game Features:")
        print("- 12 unique heroes, divided into 4 professions")
        print("- Rich item system")
        print("- Multiple combat arenas")
        print("- A complete save/load system")
        print("\\n Technical Implementation:")
        print("- Abstract classes and inheritance")
        print("- Polymorphism")
        print("- Packaging")
        print("- Exception Handling")
        print("- Decorator Pattern")
        print("- fil I/O")
        input("\\n press enter to return to main menu")